package cn.cdeden.system.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.system.api.model.LoginUser;
import cn.cdeden.system.domain.FilesLabel;
import cn.cdeden.system.domain.FilesLabelRecord;
import cn.cdeden.system.domain.dto.CoreConfigDto;
import cn.cdeden.system.domain.dto.FilesLabelDto;
import cn.cdeden.system.domain.dto.FilesLabelQueryParam;
import cn.cdeden.system.domain.enums.FileLabelTypeEnums;
import cn.cdeden.system.mapper.FilesLabelMapper;
import cn.cdeden.system.mapper.FilesLabelRecordMapper;
import cn.cdeden.system.utils.CoreConfigUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.undertow.util.BadRequestException;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.system.domain.FilesUserLabel;
import cn.cdeden.system.mapper.FilesUserLabelMapper;
import cn.cdeden.system.service.FilesUserLabelService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FilesUserLabelServiceImpl extends ServiceImpl<FilesUserLabelMapper, FilesUserLabel> implements FilesUserLabelService{

    private final FilesLabelMapper filesLabelMapper;
    private final CoreConfigUtils coreConfigUtils;
    private final FilesLabelRecordMapper recordMapper;


    @Override
    public FilesLabelDto findById(Long id) {
        FilesLabel byId = getById(id);
//        String labelType =;
        Long parentId = byId.getParentId();
        FilesLabelDto dto = MapstructUtils.convert(byId, FilesLabelDto.class);
//        FilesLabelDto dto = ConvertUtil.convert(byId, FilesLabelDto.class);
        if (
            StringUtils.equals( byId.getLabelType(), FileLabelTypeEnums.sys.getCode())  && parentId != 0L
        ) {
            FilesLabel id1 = getById(parentId);
            dto.setParentName(id1.getLabelName());
        }

        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(FilesLabelDto resources) throws BadRequestException {
        LoginUser user = LoginHelper.getLoginUser();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());

        Long id = resources.getId();

        FilesLabel byId = getById(id);
        if (ObjectUtils.isEmpty(byId)){
            throw new BadRequestException("无效的修改编号");
        }

        if (labelNameRepeat(userId, username, resources.getLabelName(),byId.getLabelType(),byId.getParentId(),id,resources.getLibraryId())){
            throw new BadRequestException("已有同名标签");
        }
        if (resources.getSort() == null  ) {
            resources.setSort(999);
        }
        FilesLabel entity = MapstructUtils.convert(resources, FilesLabel.class);
//        FilesLabel entity = ConvertUtil.convert(resources, FilesLabel.class);
        entity.setUpdateBy(username);
        entity.setUpdateId(userId);
        entity.setUpdateTime(new Date());

        entity.setCreateBy(null);
        entity.setCreateId(null);
        entity.setCreateTime(null);
        boolean a = true;
        try {
            int i = filesLabelMapper.updateById(entity);
            if ( i > 0) {
                a = true;
            }
        } catch (Exception e) {
            a = false;
        }

        return a;
    }

    @Override
    public boolean deleteByIdsAndType(Set<Long> ids, String labelType) {
        LambdaQueryWrapper<FilesLabel> wrapper = new LambdaQueryWrapper<FilesLabel>()
            .in(FilesLabel::getId,ids)
            .eq(FilesLabel::getLabelType,labelType)
            ;
        List<FilesLabel> labels = filesLabelMapper.selectList(wrapper);
//        List<FilesLabel> labels = this.list(wrapper);
        Set<Long> collect = labels.stream().map(FilesLabel::getId).collect(Collectors.toSet());
        LambdaQueryWrapper<FilesLabelRecord> queryWrapper = new LambdaQueryWrapper<FilesLabelRecord>()
            .in(FilesLabelRecord::getLabelId, collect);
        recordMapper.delete(queryWrapper);
        int delete = filesLabelMapper.delete(wrapper);
        if (delete > 0) {
            return true;
        }
        return false;
    }


    @Override
    public FilesLabel getById(Long id) {
//        FilesLabel filesLabel = filesLabelMapper.selectById(id);
//        FilesUserLabel filesUserLabel = baseMapper.selectById(id);
        return filesLabelMapper.selectById(id);
    }




    @Override
    public List<FilesLabelDto> queryAllSys(FilesLabelQueryParam query) {
        QueryWrapper<FilesLabel> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("label_type", FileLabelTypeEnums.sys.getCode());

        List<FilesLabel> list = filesLabelMapper.selectList(predicate);
//        List<FilesLabel> list = this.list(predicate);
        if (CollectionUtils.isEmpty(list)){
            return new ArrayList<>();
        }
        List<FilesLabelDto> labelDtos = MapstructUtils.convert(list, FilesLabelDto.class);
//        List<FilesLabelDto> labelDtos = ConvertUtil.convertList(list, FilesLabelDto.class);

        return this.buildTreeUseStream(labelDtos, 0L);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FilesLabelDto insert(FilesLabelDto resources) throws BadRequestException {
        LoginUser user = LoginHelper.getLoginUser();
//        FileUserDto user = FileUserUtils.getUser(); //用户信息
        String username = user.getUsername();
        String userId = Long.toString(user.getUserId());
        FilesLabel entity = MapstructUtils.convert(resources, FilesLabel.class);
//        FilesLabel entity = ConvertUtil.convert(resources, FilesLabel.class);

        String labelCreate = userId;

        String labelType = resources.getLabelType();
        if (StringUtils.equalsIgnoreCase(labelType, FileLabelTypeEnums.user.getCode())) {
            if (getMaxNum() <= getCount(userId, username)){
                throw  new BadRequestException("以达到最大的 标签数量 请删除一些标签在添加");
            }
        }else if (StringUtils.equalsIgnoreCase(labelType, FileLabelTypeEnums.team.getCode())) {
            labelCreate = resources.getTeamId(); //如果是团队标签 修改为团队id
        }


        if (labelNameRepeat(labelCreate, username, resources.getLabelName(), labelType,resources.getParentId(),null,resources.getLibraryId())){
            throw  new BadRequestException("已有同名标签");
        }
        if (resources.getSort() == null  ) {
            entity.setSort(999);
        }

        entity.setCreateBy(username);
        entity.setCreateId(userId);
        entity.setCreateTime(new Date());
        int insert = filesLabelMapper.insert(entity);
//        boolean save = this.save(entity);
        if (insert >= 0) {
            return MapstructUtils.convert(entity, FilesLabelDto.class);
//            return ConvertUtil.convert(entity, FilesLabelDto.class);
        }
//        if (save){
//            return ConvertUtil.convert(entity, FilesLabelDto.class);
//        }

        return null;
    }


    public static List<FilesLabelDto> buildTreeUseStream(List<FilesLabelDto> treeList, Long id){
        List<FilesLabelDto> list = treeList.stream()
            //过滤父节点与传递的id相同的TreeNode对象
            .filter( treeNode -> {
                Long parentId = treeNode.getParentId();
                if (parentId==null){
                    parentId=0l;
                }
                return parentId.longValue() == id.longValue();
            } )
            .map( treeNode -> {
                //递归设置孩子节点
                treeNode.setChildren(buildTreeUseStream(treeList,treeNode.getId()));
                return treeNode;
            })
            .collect(Collectors.toList());
        return list;
    }


    private Integer getMaxNum(){
        CoreConfigDto config = coreConfigUtils.getByConfigCodeAfter("SY_USER_LABEL_MAX_NUM");
        Integer i = 100;
        if (ObjectUtils.isNotEmpty(config)){
            try {
                i = Integer.valueOf(config.getConfigValue());
            }catch (Exception e){}
        }
        return i;
    }


    public Integer getCount(String userId, String username) {
        QueryWrapper<FilesLabel> wrapper = new QueryWrapper<FilesLabel>()
            .eq("create_id",userId)
            .eq("create_by",username)
            .eq("label_type",FileLabelTypeEnums.user.getCode())
            ;
        return filesLabelMapper.selectCount(wrapper).intValue();
//        return (int) this.count(wrapper);
    }


    @Override
    public boolean labelNameRepeat(String userId, String username, String labelName, String labelType, Long parentId, Long id, String libraryId){
        QueryWrapper<FilesLabel> wrapper = new QueryWrapper<FilesLabel>();
        wrapper.eq("label_name",labelName);
        if (StringUtils.equals(labelType, FileLabelTypeEnums.user.getCode())){
            wrapper = wrapper.eq("create_id",userId)
                .eq("create_by",username)
                .eq("label_type",labelType)
            ;
        }else if (StringUtils.equals(labelType, FileLabelTypeEnums.sys.getCode())){
            wrapper = wrapper.eq("label_type",labelType);
            if (parentId != null){
                wrapper.eq("parent_id",parentId);
            }
            if (libraryId != null){
                wrapper.eq("library_id",libraryId);
            }

        }else if (StringUtils.equals(labelType, FileLabelTypeEnums.team.getCode())){
            wrapper = wrapper.eq("label_type",labelType)
                .eq("team_id",userId);
        }


        if (id !=null){
            wrapper = wrapper.ne("id",id);
        }

        List<FilesLabel> list = filesLabelMapper.selectList(wrapper);
//        List<FilesLabel> list = this.list(wrapper);
        return CollectionUtils.isNotEmpty(list);
    }


}
